import xID from "./xID.js";
import {replaceByObj} from "./xUtil.js" ;
import {findJsonByCode,getAllChecked,checkNodeByCode} from "./treeUtil.js";
import xTree from "./xTree.js";

const tmplBase = `
        <div  class="{{class}}" tabindex="0" style="outline: none">
             <div type="head" class="xhead">   
                  <input class="xinput-icon" key="select" readonly/> 
                  <i class="iconfont icon-close after-icon-set" style ="display: none" title="清除" type="clear"></i>               
                  <i class="iconfont icon-dropdown after-icon-set" type="drop"></i> 
             </div> 
             <div type="main" style="display:none" class="xmain" >
                 <div type="filter"> 
                    <input key="filter" /> 
                    <i class="iconfont icon-search"></i>
                 </div>
                 <div id="{{treeId}}" type="tree-container"></div>
                 <div type="spin" class=" p-2 " style="display:none;text-align: center"> 
                    <span class="spinner-grow spinner-grow-sm text-success" ></span>
                 </div>
             </div>
        </div>`;

const tmplTitle = 'title="{{title}}"';

export default class xTreeSelect {
    /* 定义变量 开始*/
    // jquery 对象
    $root;
    $head;
    $main;
    $input;
    vBindEvent;
    vCfg;
    vSelect;
    vData;
    vTmpEvent ={};
    vClickId = 'click.'+xID.getID();
    vCtxId = 'contextmenu.'+xID.getID();
    vTreeId = xID.getID();
    vTree;
    // 0 需要同步 ，不需要同步
    vSyncStatus = 0;
    /* 定义变量 结束*/

    constructor(cfg) {
        this.$root = $('#' + cfg.el);
        this.$root.html(replaceByObj(tmplBase,{class:cfg.style||'tree-select',treeId:this.vTreeId}));
        this.vCfg = cfg;

        let innerCfg = {el:this.vTreeId,data:this.vCfg.data,check:this.vCfg.check,
            expand:this.vCfg.expand||"level 1",
            event:{  }
             };
        if(!this.vCfg.check)
            innerCfg.event.OnNodeClick=this.cbNodeSelect.bind(this);
        else
            innerCfg.event.OnCheck = this.cbNodeCheck.bind(this);

        this.vTree = new xTree(innerCfg);

        this.init();
    };

    /* 渲染区块 开始 */
    init() {
        this.$head = this.$root.find('[type="head"]');
        this.$main = this.$root.find('[type="main"]');
        this.$input = this.$root.find('input[key="select"]');
        this.$filterInput = this.$root.find('input[key="filter"]');
        this.$root.on('click','i[type="clear"]',this.evClear.bind(this));
        this.$input.on('focus',this.evFocus.bind(this));
        this.$filterInput.on('input',this.evInput.bind(this));
        this.$root.on('keydown','>div',this.evKeydown.bind(this));
        this.$root.on('click', this.evRootClick.bind(this));
        if(this.vCfg.placeholder){
            this.$input.attr('placeholder',this.vCfg.placeholder);
        }

        let title ='';
        if(this.vCfg.title)
            title = tmplTitle.replace("{{title}}",this.vCfg.title);
        this.$head.attr("title",title);
        if(this.vCfg.placeholder)
            this.$input.attr("placeholder",this.vCfg.placeholder);
        if(this.vCfg.active)
            this.initValue(this.vCfg.active);

        if(this.vCfg.readonly)
            this.setReadonly(true);
    };

    renderStatus(action,status){
        if(action=='add'){
            this.$head.addClass(status);
        }else{
            this.$head.removeClass(status);
        }
    }

    renderIcon(){
        let $drop = this.$root.find('i[type="drop"]');
        let $clear = this.$root.find('i[type="clear"]');
        if(this.vSelect){
            $drop.hide();
            $clear.show();
        }else{
            $drop.show();
            $clear.hide();
        }
    }

    initValue(value){
        if(this.vSyncStatus==1)
            return;
        let val = value;
        if(this.vCfg.check){
            this.vSelect = [];
            let codes ='';
            if(val)
                codes= val.split(',');
            for(let c of codes){
                checkNodeByCode(this.vTree.vCfg.data,c);
                this.vSelect.push(findJsonByCode(this.vTree.vCfg.data,c));
            }
            let selects = [];
            this.vSelect.forEach(d => selects.push(d.name));
            let value = selects.join(",")
            this.$input.val(value);

        }else{
            if((this.vCfg.valueType||'code') =='code')
                this.vSelect = findJsonByCode(this.vCfg.data,val)
            else
                this.vSelect = value;
            let tmp = this.vSelect?(this.vSelect.name||this.vSelect.code||''):'';
            this.$input.val(tmp);
        }

        this.renderIcon();
        this.verify();
    }

    cbNodeSelect(node){
        this.vSelect = node;
        this.$input.val(this.vSelect.name);
        this.renderIcon();
        this.$main.hide();
        if(this.vBindEvent){
            if((this.vCfg.valueType||'code') =='code')
                this.vBindEvent(this.vSelect.code)
            else
                this.vBindEvent(this.vSelect);
        }
    }

    cbNodeCheck(){

        this.vSelect = getAllChecked(this.vTree.vCfg.data);
        // 显示 name
        let selects = [];
        this.vSelect.forEach(d => selects.push(d.name));
        let value = selects.join(",")
        this.$input.val(value);

        //同步 code
        selects = [];
        this.vSelect.forEach(d => selects.push(d.code));
        value = selects.join(",");
        //console.log(this.vSelect);

        this.renderIcon();
        this.vSyncStatus = 1;
        if(this.vBindEvent){
            this.vBindEvent(value);
            this.vSyncStatus = 0;
        }
    }

    cbFilter(node,value){
        let result =true;
        if(value){
            result = false;
            let p = node;
            while(p){
                if((p.pinyin && p.pinyin.toLowerCase().indexOf(value.toLowerCase())>-1) || p.name.indexOf(value)>-1)
                    result = true;
                if(result) break;
                p = p._parent;
            }
        }
        return result;
    }

    evActive(e){
        this.renderStatus("add","active");
        $(document).on(this.vClickId,this.evOff.bind(this));
        $(document).on(this.vCtxId,this.evCtx.bind(this));
    }

    evCtx(e){
        //this.$root.find(e.target)
        if(this.$root.find(e.target).length<1){
            this.evOff(e)
        }
    }

    evClear(e){
        this.vSelect = null
        this.$input.val('');
        this.renderIcon();

        if(this.vBindEvent){
            if((this.vCfg.valueType||'code') =='code')
                this.vBindEvent(this.vSelect.code)
            else
                this.vBindEvent(this.vSelect);
        }

    };

    evFocus(e){
        if(this.vCfg.readonly)
            return;
        let _this = this;
        function cbLoadSuccess(data){
            _this.setData(data);
            _this.$main.find('div[type="filter"]').show();
            _this.$main.find('div[type="tree-container"]').show();
            _this.$main.find('div[type="spin"]').hide();
        }
        if(this.vCfg.load){
            this.$main.find('div[type="filter"]').hide();
            this.$main.find('div[type="tree-container"]').hide();
            this.$main.find('div[type="spin"]').show();
            this.vCfg.load(cbLoadSuccess);
        }
        this.$main.show();
        this.evActive(null);
    }

    evInput(e){
        this.vTree.filter(this.cbFilter,this.$filterInput.val())
    }

    evKeydown(e){
        let keynum = window.event ? e.keyCode : e.which;
        switch(keynum){
            //tab 失去焦点
            case 9:
                this.evOff(e);
                break;
            case 27:
                this.$input.focus();
                this.$main.hide();
                break;
        }
    }

    evRootClick(e){
        this.vTmpEvent.timeStamp = e.timeStamp;
        this.vTmpEvent.target =e.target;
    };

    evOff(e){
        if((e.type=='keydown'|| e.type=="contextmenu"||
                (e.type=='click' && (this.vTmpEvent.timeStamp !=e.timeStamp || this.vTmpEvent.target !=e.target)))){
            this.$main.hide();
            this.renderStatus('remove','active');
            this.verify();
            $(document).unbind(this.vClickId);
        }
    }

    setReadonly(status){
        this.vCfg.readonly = status;
        if(status){
             this.renderStatus("add","readonly");
        }else{
            this.renderStatus("remove","readonly");
        }
    }

    setBindEvent(event){
        this.vBindEvent = event;
    };

    setValue(value){
        this.initValue(value);
    };

    setData(data){
        this.vCfg.data =data;
        this.vTree.vCfg.data = data;
        this.vTree.refresh();
        //this.renderIcon();
    }

    verify() {
        let result = true;
        if(this.vCfg.mandatory ){
            if(!this.vSelect || this.vSelect.length<1){
                this.renderStatus("remove",'valid');
                this.renderStatus("add","invalid");
                result =false
            }else {
                this.renderStatus("remove",'invalid');
                this.renderStatus("add","valid");
            }
        }
        return result;
    }

    getSelect(){
        return this.vSelect;
    }
}